The present disclosure relates generally to memory management, and, in particular, to memory management server-side scripting language runtime system.
Runtime systems for the scripting of programming languages often consume considerable amounts of central processing unit (CPU) time for dynamic memory management. Programming and scripting languages typically include specific function to allocate and free memory. For example, the functions “malloc” and “free” are typically utilized, respectively, for allocating and freeing memory.
The “malloc” function is the basic function used to allocate memory on the heap (dynamic memory) in the C and C++ programming languages. Its function prototype is void *malloc(size_t size), which allocates “size” bytes of memory. If the allocation succeeds, malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. Memory allocated via malloc is persistent: it will continue to exist until the program terminates or the memory is explicitly unallocated by the programmer (that is, the block is said to be “freed”).
Freeing blocks is achieved by use of the “free” function. Its prototype is void free(void *pointer), which releases the block of memory pointed to by “pointer.” Pointer must have been previously returned by malloc or calloc (cache allocation) or a function which uses one of these functions (e.g., strdup), and must only be passed to the function free once.
To keep the entire heap in a healthy state, general purpose memory allocators utilizing malloc and free have to perform many activities in addition to allocation and freeing activities. Such activities shall be referred to herein as “bookkeeping activities.” A general-purpose memory allocator often consumes a large fraction of the CPU's time in malloc and free for the bookkeeping activities. The actual implementation of the bookkeeping activities depends on the implementation of the allocator and is a major area of innovation. One example of bookkeeping used in a well known a memory allocator sorts all of the objects in the free lists in order of their size, coalesces multiple small objects into large objects, and splits large objects into small objects in response to requests. Other bookkeeping activities may include de-fragmenting the unallocated memory chunks. In short, memory allocators often spent a larger amount of CPU time for bookkeeping activities than for the allocations themselves. These bookkeeping activities are, however, necessary for general-purpose allocators to avoid gradual performance degradations of the applications, both in execution time and memory consumption.
Scripting languages, are becoming increasingly popular for developing Web applications even for large commercial websites. An example of such a scripting language includes hypertext preprocessor (PHP). PHP was originally designed for producing dynamic web pages and is used for server-side scripting. PHP may also be used from a command line interface or in standalone graphical applications. Another example of such a scripting language is Ruby.
One important characteristic of Web applications written in such scripting languages is that most server-side memory objects allocated during a transaction are transaction scoped. That is, the memory objects only exist during that transaction and these objects can be destroyed after the transaction ends. The current PHP server-side runtime initializes a heap (a portion of dynamic memory) for transaction-scoped objects so that it can reliably reclaim all of the memory allocated to them at the end of each transaction by discarding the entire heap.
Region-based memory management is a well-known technique to reduce the overhead of memory management for applications that destroy many objects together and reclaim their memory. For example, scripting languages may utilize region-based memory management.
The region-based allocators obtain a large chunk of memory from an underlying allocator and the allocation may be accomplished by merely incrementing a pointer. The region-based allocator reclaims all of the memory allocated within a region when the region is destroyed by calling the “freeAll” function which decrements the pointer. Thus, the overhead of both allocation and deallocation is fairly small. Some real-world applications use this technique. For example the Apache HTTP server has a region-based custom memory allocator that frees and reclaims all of the objects allocated to serving an HTTP connection when that connection terminates. Extensive analyses for many workloads using custom memory allocators has been conducted and reported that region-based custom allocators often improved the performance of applications, though other kinds of custom allocators did not improve the performance compared to a state-of-the-art general-purpose memory allocator. Further, region-based memory management may suffer from two particular problems: excessive memory consumption and performance degradation of applications due to increased bus transactions. In addition, region-based memory management does not allow for pre-object free commands.
What is needed, therefore, is a memory management approach that efficiently allocates and frees memory without degrading system performance.